<?php
require_once("AuthorDAO.php");
require_once("BookDAO.php");
require_once("ComicDAO.php");

/***
 * 为comic.solor.cn 提供公用接口，封装底层的一些复杂操作... 
 * 为单例类
 */
class ComicFacade
{
    /// 代表作者的DAO
    var $adao;
    /// 代表漫画的DAO
    var $bdao;
    /// 代表漫画的DAO
    var $cdao;
    /// 构造函数， 实例话各个DAO
    
    /// 正真的实例
    static $me = null;
    
    private function __construct()
    {
        $this->adao = new AuthorDAO;  
        $this->bdao = new BookDAO;  
        $this->cdao = new ComicDAO;  
    }
    /// 构造实例
    static function instance()
    {
        if (self::$me==null)
        {
            return new ComicFacade();
        }
        else
        {
            return self::$me;
        }
    }

    /**
     * 取得所有的作者列表
     */
    function getAllAuthors()
    {
        return $this->adao->getAll();
    }

    /**
     * 根据作者id取得漫画列表
     * @param $id 作者id
     * @returns VO 的数组
     */
    function getComicsByAuthorId($id)
    {
        $id=intval($id);
        $vo=new Comic();
        $vo->set("authors_id", $id);
        return $this->cdao->getByCol(array("authors_id"), array($vo));
    }

    /**
     * 对漫画的图片进行编码
     * @param $bookId 册id
     * @param $page 第几页的信息
     * @return 图片文件的文件名，不包括后缀
     */
    function encodeComicImg($bookId, $page)
    {
        return md5($bookId . "#" . $page);
    }
    

    /**
     * 得到本地图片的地址
     * @param $comic 漫画id
     * @param $series 第几系列, 如果没有多个系列这里为0
     * @param $volume 第几册
     * @param $ext 扩展名，默认为png
     * @return 本地图片地址的字符串
     */ 
    function getLocalFile($comic, $series, $volume, $page, $ext="png")
    {
        return C_LOCAL_IMAGE_BASE_PATH . "{$comic}/{$series}/{$volume}/{$page}.{$ext}";
    }
    
    /**
     * 取得远程的图片的url
     * @param $bookId 册id
     * @param $page 第几页的信息
     * @return 返回用户可以访问的url地址的数组 array("o"=>"原图url", "t", "导航图url");
     */
    function getRemoteUrls($bookId, $page)
    {
        $encodedFile = $this->encodeComicImg($bookId, $page);
        $firstChar = substr($encodedFile, 0, 1);
        $o = C_REMOTE_IMAGE_BASE_URL. "$firstChar/$page/o_{$encodedFile}.png";
        $t = C_REMOTE_IMAGE_BASE_URL . "$firstChar/$page/t_{$encodedFile}.png";
        return array("o"=>$o, "t"=>$t);
    }
    
    /**
     * 取得一册漫画的所有图片
     * @param $bookId 册id
     * @param $total 改册共有多少页,如果不指定的话，测从数据库中取得，并显示
     */
    function getAllUrlsByBookId($bookId, $total = null)
    {
        if ($total === null)
        {
            $vo = $this->bdao->getOneBy("id", $bookId);
            $total = $vo->get("pages");
        }
        if ($total <= 0 ) return array();
        $ret = array();
        for($i = 1; $i <= $total; $i++)
        {
            $ret[$i] = $this->getRemoteUrls($bookId, $i);
        }
        return $ret;
    }

    /**
     * 取得一册漫画的信息
     * @param $bookId 册id
     * @return VO 
     */
     function getBookById($bookId)
     {
         return $this->bdao->getOneBy("id", $bookId);
     }


    /**
     * 通过命令行的imagemagick取得文件大小信息
     * @param $file 文件地址
     * @return 文件大小 array("width" => xxx, "height"=>yyy); 或者 false
     */ 
    function getImgSize($file)
    {
       $file = escapeshellarg($file);
       $str = C_IMK_IDENTIFY . " -format %wx%h $file";
       $r = `$str`;
       if (empty($r)) return false;
       $ar = explode("x",$r);
       if (count($ar) != 2) return false;
       return array("width" => trim($ar[0]), "height" => trim($ar[1]));
    }

    /**
     * 转换文件为缩略图
     * @param $source 源文件 
     * @param $target 目标文件
     * @return 是否成功
     */ 
     function imgToThumb($source, $target)
     {
         $osize = $this->getImgSize($source) ;
         if (empty($osize)) return false;
         $rawWidth = $osize["width"];
         $rawHeight = $osize["height"];
         $whScale = $rawWidth/$rawHeight;
         $STD_SCALE_RECT = C_T_IMG_WIDTH/C_T_IMG_HEIGHT;
         if($whScale >= $STD_SCALE_RECT)
         {
             $scaleWidth = ceil($rawHeight * $STD_SCALE_RECT);
             $left = ceil(($rawWidth-$scaleWidth)/2);
             $cropStr =  "-crop {$scaleWidth}x{$rawHeight}+{$left}";
         }
         else
         {
             $scaleHeight = ceil($rawWidth/$STD_SCALE_RECT);
             $top = ceil(($rawHeight-$scaleHeight)/2);
             $cropStr =  "-crop {$rawWidth}x{$scaleHeight}+0+{$top}";
         }
         $convert = C_IMK_CONVERT;
         $w = C_T_IMG_WIDTH;
         $h = C_T_IMG_HEIGHT;
         $exec = <<<CMD
         $convert "{$source}" {$cropStr} -resize {$w}x{$h}\>! "$target"
CMD;

        $status = null;
        system($exec, $status);

        if ($status) {
            error_log("convert $source to $target error");
            return false;
        }
        return $target;
     }

     /**
      *根据bookid获取相关信息
      * @param $bookId;
      * @return book 相关信息 :
      *     @code
      *     

错误情况
{
    isErr: true
    err :{
        errType:   (int) [ERROR_TYPE],
        errCode : (int) [ERROR_CODE],
        errMsg:  (string) [ERROR_MSG]  
    }
}

成功情况

{
    isErr :false
    data:{
        bookId: ,
        book: 
        {
            ... book related data in db
        },
        comic :
        {
            ... comic related data in db
        },
        author:
        {
            .... author related data in db  
        },
        "pages":
        {
            url datas 
        }
    }
}
*     
      *     @endcode
      */
      function getJsonByBookId($bookId)
      {
          $ret = array();
          $vo= $this->getBookById($bookId);
          if (empty($vo))
          {
              $ret['isErr'] = true; 
              $ret['err'] = array("errType" => 0, "errCode" => 1 , "errMsg" => "get book err");
              return $ret;
          }

          $comicId = $vo->get("comics_id");
          $cvo = $this->cdao->getOneBy("id", $comicId);
          if(empty($cvo))
          {
              $ret['isErr'] = true;
              $ret['err'] = array("errType" => 0, "errCode" => 0 , "errMsg" => "get comic err");
              return $ret;

          }
          $authorId = $cvo->get("authors_id");
          $avo = $this->adao->getOneBy("id", $authorId);
          if(empty($avo))
          {
              $ret['isErr'] = true;
              $ret['err'] = array("errType" => 0, "errCode" => 0 , "errMsg" => "get author err");
              return $ret;
          }
          $total = $vo->get("pages");
          $pages = $this->getAllUrlsByBookId($bookId, $total);
          $ret['isErr'] = false;
          $ret['data'] = array(
              'bookId'=> $bookId,
              "book" => $vo->getEntity(),
              "comic" => $cvo->getEntity(),
              "author" => $avo->getEntity(),
              "pages" => $pages 
          );
          return $ret;
      }
}
?>
